package com.diaohaiwen.common.util;

import cn.hutool.core.util.ClassUtil;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.type.filter.AssignableTypeFilter;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;

/**
 * @author 刁海文
 * @since 2024/1/14 19:07
 */
public class ClassUtils extends ClassUtil {

    public static <T> Set<Class<T>> children(Class<T> clazz, String basePackage) {

        Set<Class<T>> classes = new HashSet<>();
        try {
            ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
            provider.addIncludeFilter(new AssignableTypeFilter(clazz));
            // scan in org.example.package
            Set<BeanDefinition> components = provider.findCandidateComponents(basePackage);
            for (BeanDefinition component : components) {
                Class<T> cls = (Class<T>) Class.forName(component.getBeanClassName());
                classes.add(cls);
            }

        } catch (ClassNotFoundException e) {

        }
        return classes;
    }


    public static <T> T newInstance(Class<T> clazz) {
        try {
            return clazz.getDeclaredConstructor().newInstance();
        } catch (InvocationTargetException | NoSuchMethodException | IllegalAccessException |
                 InstantiationException e) {
            throw new RuntimeException(e);
        }
    }


    public static <T> T methodInvoke(Object clazz, Method method) {
        try {
            Object invoke = method.invoke(clazz);
            return (T) invoke;
        } catch (InvocationTargetException | IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }
}
